"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.OAuth2Manager = void 0;
const axios_1 = __importDefault(require("axios"));
const moment_1 = __importDefault(require("moment"));
const urls_1 = require("../lib/urls");
const environment_1 = require("../lib/environment");
const logger_1 = require("../lib/logger");
const lang_1 = require("../utils/lang");
const i18nKey = 'models.OAuth2Manager';
class OAuth2Manager {
    account;
    writeTokenInfo;
    refreshTokenRequest;
    constructor(account, writeTokenInfo) {
        this.writeTokenInfo = writeTokenInfo;
        this.refreshTokenRequest = null;
        this.account = account;
        if (this.account.env) {
            this.account.env = (0, environment_1.getValidEnv)(this.account.env, '');
        }
    }
    async accessToken() {
        if (!this.account.auth.tokenInfo.refreshToken) {
            throw new Error((0, lang_1.i18n)(`${i18nKey}.errors.missingRefreshToken`, {
                accountId: this.account.accountId,
            }));
        }
        if (!this.account.auth.tokenInfo.accessToken ||
            (0, moment_1.default)()
                .add(5, 'minutes')
                .isAfter((0, moment_1.default)(new Date(this.account.auth.tokenInfo.expiresAt || '')))) {
            await this.refreshAccessToken();
        }
        return this.account.auth.tokenInfo.accessToken;
    }
    async fetchAccessToken(exchangeProof) {
        logger_1.logger.debug((0, lang_1.i18n)(`${i18nKey}.fetchingAccessToken`, {
            accountId: this.account.accountId,
            clientId: this.account.auth.clientId,
        }));
        try {
            const { data } = await (0, axios_1.default)({
                url: `${(0, urls_1.getHubSpotApiOrigin)((0, environment_1.getValidEnv)(this.account.env))}/oauth/v1/token`,
                method: 'post',
                data: exchangeProof,
                headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
            });
            this.refreshTokenRequest = data;
            const { refresh_token: refreshToken, access_token: accessToken, expires_in: expiresIn, } = data;
            if (!this.account.auth.tokenInfo) {
                this.account.auth.tokenInfo = {};
            }
            this.account.auth.tokenInfo.refreshToken = refreshToken;
            this.account.auth.tokenInfo.accessToken = accessToken;
            this.account.auth.tokenInfo.expiresAt = (0, moment_1.default)()
                .add(Math.round(parseInt(expiresIn) * 0.75), 'seconds')
                .toString();
            if (this.writeTokenInfo) {
                logger_1.logger.debug((0, lang_1.i18n)(`${i18nKey}.updatingTokenInfo`, {
                    accountId: this.account.accountId,
                    clientId: this.account.auth.clientId,
                }));
                this.writeTokenInfo(this.account.auth.tokenInfo);
            }
        }
        finally {
            this.refreshTokenRequest = null;
        }
    }
    async exchangeForTokens(exchangeProof) {
        if (this.refreshTokenRequest) {
            logger_1.logger.debug((0, lang_1.i18n)(`${i18nKey}.refreshingAccessToken`, {
                accountId: this.account.accountId,
                clientId: this.account.auth.clientId,
            }));
            await this.refreshTokenRequest;
        }
        else {
            await this.fetchAccessToken(exchangeProof);
        }
    }
    async refreshAccessToken() {
        const refreshTokenProof = {
            grant_type: 'refresh_token',
            client_id: this.account.auth.clientId,
            client_secret: this.account.auth.clientSecret,
            refresh_token: this.account.auth.tokenInfo.refreshToken,
        };
        await this.exchangeForTokens(refreshTokenProof);
    }
}
exports.OAuth2Manager = OAuth2Manager;
